
import time
from datetime import datetime, timedelta
from flask import render_template, abort
from flask_mail import Message
import itsdangerous
from itsdangerous import SignatureExpired, BadData
from src import common
from utils.initApp import mysql, mail, app


class AuthService:
    def __init__(self, describe):
        self.its8s = itsdangerous.TimedJSONWebSignatureSerializer(
            app.config["PRIVATE_KEY"],
            expires_in=app.config["TIMEOUT_EMAIL"]
        )
        self.auth_describe = describe
        return

    def __construct_user_info(self, user):

        data = dict()
        data['userName'] = user['userName']
        data['userId'] = user['userId']
        data['time'] = str(time.time())

        info = dict()
        info['userId'] = user['userId']
        info['token'] = common.construct_token(data)
        # add_user_token(_data['username'], _data['token'])
        return info

    def __send_email(self, data):
        title = 'nebula-云盘系统密码重置邮件'
        sender = app.config['MAIL_USERNAME']
        email = data['email']
        user_name = data["userName"]
        now_time = data["time"]
        reset_url = 'http://127.0.0.1:9009/auth/reset/' + data["token"]

        msg = Message(title, sender=sender, recipients=[email])
        msg.html = render_template(
            "forget_password.html",
            now_time=now_time,
            user_name=user_name,
            reset_url=reset_url,
        )
        mail.send(msg)
        return

    def login(self, values):
        sha256_password = common.make_sha256(values['password'])
        user = mysql.get('user', values, 'userName')

        if not user:
            msg = '用户不存在'
            return None,  msg, -1,
        elif not sha256_password == user['password']:
            msg = '密码错误'
            return None,  msg, -1,
        else:
            data = self.__construct_user_info(user)
            return data,  "", 0,

    def register(self, values):
        sha256_password = common.make_sha256(values['password'])
        user = mysql.get('user', values, 'userName')

        record = dict()
        record['userName'] = values["userName"]
        record['password'] = sha256_password
        record['userId'] = common.create_id()

        if user:
            raise Exception('用户名已存在')
        else:
            mysql.insert('user', record)
        return {}

    def forget(self, values):
        user = mysql.get('user', values, "email")

        if(user):

            token_data = dict()
            token_data["userId"] = user["userId"]
            token_data["userName"] = user["userName"]
            token_data["email"] = user["email"]
            token_data["id"] = common.create_id()

            reset_data = dict()
            reset_data['id'] = token_data["id"]
            reset_data['token'] = self.its8s.dumps(token_data).decode()

            email_data = dict()
            email_data['token'] = reset_data['token']
            email_data["time"] = common.get_now_time()
            email_data["email"] = user["email"]
            email_data["userName"] = user["userName"]

            mysql.insert('reset', reset_data)
            self.__send_email(email_data)
            return None, "ok", 0,
        else:
            return None, "用户不存在", -1,

    def reset(self, values):
        token = values["token"]
        now_time = common.get_now_time()
        password = common.get_ranstr(6)

        try:
            token_data = self.its8s.loads(token)
            user_name = token_data['userName']

            data = dict()
            data['password'] = common.make_sha256(password)
            data['userId'] = token_data["userId"]

            reset_data = dict()
            reset_data["id"] = token_data["id"]

            reset_record = mysql.get('reset', reset_data)

            if reset_record:
                mysql.update('user', data, "userId")
                mysql.delete('reset', reset_data)
                return render_template(
                    'reset_password.html',
                    now_time=now_time,
                    user_name=user_name,
                    password=password,
                    timeout=False,
                )

            else:
                raise(SignatureExpired('err'))

        except SignatureExpired:
            return render_template(
                'reset_password.html',
                now_time=now_time,
                timeout=True,
            )

        except BadData:
            abort(404)
